
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>7、上传下载 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>7、上传下载 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在客户端实现文件上传功能时，HTML表单必须满足哪三个关键条件？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. 请求方式必须是 post； 2. 需要使用 <input type="file"> 组件； 3. 表单的 enctype 属性必须设置为 "multipart/form-data"。</div>
          </div>
          <div class="card-source">来源: 文件上传原理</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">使用 Apache Commons-fileupload 组件进行文件上传时，必须引入哪两个核心的 JAR 包？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">需要导入 Commons-fileupload 和 commons-io 这两个JAR包。从 Commons-fileupload 1.1 版本开始，其工作时需要 commons-io 包的支持。</div>
          </div>
          <div class="card-source">来源: 上传开源框架-commons-upload</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在服务器端，使用 Commons-fileupload 框架解析上传请求的核心三步流程是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. 创建一个 DiskFileItemFactory 对象； 2. 基于该 Factory 创建一个 ServletFileUpload 对象； 3. 调用 ServletFileUpload 对象的 parseRequest 方法来解析请求，从而得到一个包含所有表单项（FileItem）的列表。</div>
          </div>
          <div class="card-source">来源: 文件上传案例</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">如果上传的文件名与服务器上已有的文件重复，文档中针对服务端提出了哪两种解决方案？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">方案一（针对图片资源）：为文件重新取一个唯一的名字以避免覆盖。方案二（针对下载资源）：保留原有名字，但通过创建带有时间戳的目录结构（如 `年\月\日\时分秒\文件名`）来确保路径的唯一性。</div>
          </div>
          <div class="card-source">来源: 思考题：文件名重复了怎么办？</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">除了文件数据，如何从一个 `multipart/form-data` 请求中获取其他普通的表单字段值？文档推荐了哪个框架来简化此过程？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">可以通过遍历解析后得到的 FileItem 列表，并使用 `item.getString()` 方法来获取非文件表单项的值。为了更方便地将这些值封装到对象中，文档推荐使用另一个开源框架 BeanUtils。</div>
          </div>
          <div class="card-source">来源: 获取完整的表单数据</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在使用 Servlet 实现文件下载时，如何通过设置响应头来强制浏览器弹出“另存为”对话框，而不是直接在浏览器中打开文件？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">通过设置 `Content-disposition` 响应头，并将其值设为 `attachment`，同时通过 `fileName` 参数指定下载时的文件名。例如：`response.setHeader("Content-disposition", "attachment;fileName="+fileName);`。</div>
          </div>
          <div class="card-source">来源: 文件下载</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">文档中提到了哪两种主要的文件下载实现方式？在什么情况下推荐使用Servlet来实现下载？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">主要方式有两种：超链接下载和 Servlet 下载。当遇到超链接无法处理的复杂情况时，例如需要权限控制或处理中文文件名编码等问题，就推荐使用 Servlet 通过流的方式来完成下载。</div>
          </div>
          <div class="card-source">来源: 文件下载</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">针对上传的文件名包含中文的情况，文档建议了哪两种处理策略？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">策略一：直接将其改名，不使用原来的中文名，这种方式适用于直接展示的图片。策略二：保留其中文名，但文档指出此策略更适用于供下载的压缩文件资源。</div>
          </div>
          <div class="card-source">来源: 文件上传案例</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在处理完整的表单数据时，文档中提到的 BeanUtils 框架依赖于哪个 JAR 包？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">BeanUtils 框架除了自身的 JAR 包外，还依赖于 commons-logging.jar。</div>
          </div>
          <div class="card-source">来源: 获取完整的表单数据</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
